﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExpertSystem.Interfaces;

namespace ExpertSystem.Domains
{
    
    public class Conjunct : IConjunct 
    {
        private  List<IVariable> _variables;
        private IFunction _function;
        private bool _tryresolved =  false;

        public Conjunct()
        {
            _variables = new List<IVariable>();
        }

        public List<IVariable> Variables
        {
            get { return _variables; }
        }

        public string Description
        {
            get { return this.ToString(); }
        }

        public IFunction Function
        {
            get { return _function; }
        }

        public Conjunct(List<IVariable> variables, IFunction function, List<IVariable> func_variables)
        {
            _variables = variables;
            _function = function;
            _function.Variables = func_variables;
        }

        #region Implementation of IConjunct

        /// <summary>
        /// Может ли найдено значение коньюнкта
        /// </summary>
        /// <returns></returns>
        public bool CanBeResolved()
        {
           return !_variables.Any(x => (!x.HaveValue() || !x.CanBeResolved()) && !_function.CanBeResolved()) && !_tryresolved;
        }

        /// <summary>
        /// Значение возвращаемое коньюнктом
        /// </summary>
        /// <returns></returns>
        public bool Value()
        {
            return _function.Calculate();
        }

        public void Resolve()
        {
         // Активация правила
            foreach (IVariable variable in _variables.Where(variable => variable.CanBeResolved() && !variable.HaveValue()))
            {
                variable.Resolve();
            }
            _tryresolved = true;
        }

        public IVariable CanNotResolvedVariable()
        {
            return _variables.First(variable => !variable.CanBeResolved());
        }

        public bool TryToResolve
        {
            get { return _tryresolved; }
        }

        public bool VarValueCorrect
        {
            get
            {
                if (!_variables.Any(x => !x.HaveValue()))
                {
                    return Value();
                }
                return true;
            }
        }

        public bool CanReturnTrueValue()
        {
            if(_function.CanBeCalculated())
            {
                return _function.Calculate();
            }
            else {
                return true;
            }
        
        }

        #endregion

        public override string ToString()
        {
            string result = "";
            result += "(" + _variables.First().Name + " " + _function.Name + " " + _function.Variables.Last().Value + ")";
            return result;
        }
    }
}
